package automately.core.services.api.routers;
import automately.core.data.Job;
import automately.core.data.User;
import automately.core.data.UserData;
import com.hazelcast.core.IMap;
import io.jsync.Handler;
import io.jsync.app.ClusterApp;
import io.jsync.app.core.Cluster;
import io.jsync.app.core.Config;
import io.jsync.http.HttpServerRequest;
import io.jsync.json.JsonObject;
import io.jsync.json.impl.Base64;
import io.netty.handler.codec.http.HttpHeaders;
public abstract class ApiHandler implements Handler<HttpServerRequest> {
private Cluster cluster;
private Config config;
private boolean secure = true;
public ApiHandler() {
this(true);
}
public ApiHandler(boolean secure) {
this.cluster = cluster();
this.config = cluster.config();
this.secure = secure;
}
protected Cluster cluster() {
if (cluster == null) {
cluster = ClusterApp.activeInstance().cluster();
}
return cluster;
}
protected IMap<String, User> users() {
return cluster().data().persistentMap("users");
}
protected IMap<String, Job> jobs() {
return cluster().data().persistentMap("jobs");
}
/**
* This returns the child JsonObject for the config
* automately.core
*
* @return JsonObject
*/
protected JsonObject coreConfig() {
Cluster cluster = cluster();
JsonObject rawConfig = cluster.config().rawConfig();
if (!rawConfig.containsField("automately")) {
rawConfig.putValue("automately", new JsonObject().putValue("core", new JsonObject()));
}
return rawConfig.getObject("automately").getObject("core");
}
protected void defaultResponse(HttpServerRequest req) {
JsonObject response = new JsonObject();
response.putString("message", "Bad Request");
response.putString("description", "This is not a valid API request.");
req.response().setStatusCode(400);
req.response().setContentType("application/json");
req.response().end(response.encode(false));
}
protected void errorResponse(HttpServerRequest req, String message, String description, Integer statusCode) {
JsonObject response = new JsonObject();
response.putString("message", message);
response.putString("description", description);
req.response().setStatusCode(statusCode);
req.response().setContentType("application/json");
req.response().end(response.encode(false));
}
@Override
public void handle(HttpServerRequest req) {
req.response().setContentType("application/json"); // Set the content type firstx
/**
* Begin Authorization
*/
User mUser = null;
boolean authenticated = false;
if (req.headers().contains(HttpHeaders.Names.AUTHORIZATION)) {
String authString = req.headers().get(HttpHeaders.Names.AUTHORIZATION);
if (authString.split(" ").length > 1) {
authString = authString.split(" ")[1];
String decodedAuth = org.apache.commons.codec.binary.StringUtils.newStringUtf8(Base64.decode(authString));
if (decodedAuth != null) {
if (decodedAuth.split(":").length > 1) {
String username = decodedAuth.split(":")[0].trim();
String key = decodedAuth.split(":")[1].trim();
if (!username.equals("") && !key.equals("") && UserData.getUserByUsername(username) != null) {
User user = UserData.getUserByUsername(username);
if(user != null){
if (UserData.validateUserKey(user, key)) {
mUser = user;
authenticated = true;
}
}
}
}
}
}
}
// Default Unauthorized if we are not authenticated
if (!authenticated && secure) {
if (!handleUnauthorized(req)) {
req.response().putHeader(HttpHeaders.Names.WWW_AUTHENTICATE, "Basic realm=\"username and api key required\"");
errorResponse(req, "Unauthorized", "You are unauthorized to make this request", 401);
return;
}
}
final User finalUser = mUser;
/**
* End Authorization
*/
try {
handleAuthorized(req, finalUser);
} catch (Exception e){
errorResponse(req, "API Error", e.getMessage(), 500);
}
}
public abstract void handleAuthorized(HttpServerRequest request, User user);
public abstract boolean handleUnauthorized(HttpServerRequest request);
}